import pynput
from threading import Event
from json import loads
from time import perf_counter,sleep

clicked = []
pressed = []


def read_from_file(filename):
    with open(filename, 'r') as file:
        return file.readlines()


def move(data: dict, mouse_controller):
    try:
        mouse_controller.position = (data['x'], data['y'])
    except Exception as e:
        print(f'\r\033[31m播放时遇到了一个错误，在move({data!r})，错误类型{e.__class__.__name__}，错误信息{str(e)}\033[0m')

dict_for_click = {'left': pynput.mouse.Button.left,
                  'middle': pynput.mouse.Button.middle,
                  'right': pynput.mouse.Button.right}


def click(data: dict, mouse_controller):
    try:
        button = dict_for_click[data['button']]
        if data['pressed']:
            mouse_controller.press(button)
            clicked.append({'button': data['button']})
        else:
            mouse_controller.release(button)
            try:
                clicked.remove({'button': data['button']})
            except ValueError:
                pass
    except Exception as e:
        print(f'\r\033[31m播放时遇到了一个错误，在click({data!r})，错误类型{e.__class__.__name__}，错误信息{str(e)}\033[0m')


def scroll(data: dict, mouse_controller):
    try:
        mouse_controller.scroll(data['x'], data['y'])
    except Exception as e:
        print(f'\r\033[31m播放时遇到了一个错误，在scroll({data!r})，错误类型{e.__class__.__name__}，错误信息{str(e)}\033[0m')


def press(data: dict, keyboard_controller):
    try:
        if data['key_type'] == 'Key':
            key = getattr(pynput.keyboard.Key, data['key'])
            keyboard_controller.press(key)
            pressed.append({'key_type': data['key_type'], 'key': data['key']})
        else:
            keyboard_controller.press(data['key'])
            pressed.append({'key_type': data['key_type'], 'key': data['key']})
    except Exception as e:
        print(f'\r\033[31m播放时遇到了一个错误，在press({data!r})，错误类型{e.__class__.__name__}，错误信息{str(e)}\033[0m')


def release(data: dict, keyboard_controller):
    try:
        if data['key_type'] == 'Key':
            key = getattr(pynput.keyboard.Key, data['key'])
            keyboard_controller.release(key)
            pressed.remove({'key_type': data['key_type'], 'key': data['key']})
        else:
            keyboard_controller.release(data['key'])
            pressed.remove({'key_type': data['key_type'], 'key': data['key']})
    except ValueError:
        pass
    except Exception as e:
        print(f'\r\033[31m播放时遇到了一个错误，在release({data!r})，错误类型{e.__class__.__name__}，错误信息{str(e)}\033[0m')


def start_play(filename: str, done: Event):
    try:
        lines = read_from_file(filename)
    except FileNotFoundError:
        print(f'\033[31m文件{filename}不存在，请检查后重试\033[0m')
        return
    mouse_controller = pynput.mouse.Controller()
    keyboard_controller = pynput.keyboard.Controller()
    start_time = perf_counter()
    
    if lines[-1]=='':
        del lines[-1]
    
    total_time=round(loads(lines[-1])['time'],2)
    for line in lines:
        line_data = loads(line)
        while line_data['time'] > perf_counter() - start_time:
            sleep(0.002)
            print('\r正在播放:' + str(round(perf_counter()-start_time,2)) + '/'+str(total_time)+'s('+str(int((perf_counter()-start_time)/total_time*100))+'%)', end='', flush=True)
        match line_data['type']:
            case 'move':
                move(line_data, mouse_controller)
            case 'click':
                click(line_data, mouse_controller)
            case 'scroll':
                scroll(line_data, mouse_controller)
            case 'press':
                press(line_data, keyboard_controller)
            case 'release':
                release(line_data, keyboard_controller)
        if done.is_set():
            break
    if clicked:
        for _clicked in clicked:
            click({**_clicked, 'pressed': False}, mouse_controller)
    if pressed:
        for _pressed in pressed:
            release(_pressed, keyboard_controller)


if __name__ == '__main__':
    start_play('../saves/1.txt', Event())
